﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Xml.Serialization;
using Microsoft.Win32;
using System.Threading;
using System.ComponentModel;

namespace SketlonBackOffice
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        #region Gloabals
        private int captureCount = 0;
        private double FirstXPos = 0;
        private double FirstYPos = 0;
        object MovingObject = null;
        List<ListBoxItem> listItems = new List<ListBoxItem>();
        List<Line> JointLines;
        List<SketlonFrame> SketlonList = new List<SketlonFrame>();
        List<Button> buttonList = new List<Button>();
        int UniqueRepeatIndex = 0;
        #endregion
        public MainWindow()
        {


            InitializeComponent();
            JointLines = new List<Line>();
            for (int i = 0; i < 10; i++)
            {
                JointLines.Add(new Line());
            }
        }
        protected override void OnContentRendered(EventArgs e)
        {
            base.OnContentRendered(e);
            DrawLines(JointLines);
            buttonList.Add(HeadJoint);
            buttonList.Add(ElbowLeft);
            buttonList.Add(ElbowRight);
            buttonList.Add(HandLeft);
            buttonList.Add(HandRight);
            buttonList.Add(BackCenter);
            buttonList.Add(KneeLeft);
            buttonList.Add(KneeRight);
            buttonList.Add(FootLeft);
            buttonList.Add(FootRight);
            CaptureClick(null, null);
        }

        private void Head_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            FirstXPos = e.GetPosition(sender as Control).X;
            FirstYPos = e.GetPosition(sender as Control).Y;
            MovingObject = sender;
        }

        private void Head_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
        {
            MovingObject = null;
        }

        private void Head_MouseMove(object sender, MouseEventArgs e)
        {

            if (e.LeftButton == MouseButtonState.Pressed &&
                        sender == MovingObject)
            {
                Button btn = sender as Button;
                int buttonIndex = Convert.ToInt32(btn.CommandParameter);
                double newXValue = e.GetPosition((sender as Control).Parent as Control).X - FirstXPos - 270;
                double newYValue = e.GetPosition((sender as Control).Parent as Control).Y - FirstYPos;
                (sender as Control).SetValue(Canvas.LeftProperty, newXValue.ToFloor());

                (sender as Control).SetValue(Canvas.TopProperty, newYValue.ToFloor());
                if (buttonIndex == 1 || buttonIndex == 2 || buttonIndex == 6 || buttonIndex == 7)
                {
                    JointLines[buttonIndex + 2].SetValue(Line.X2Property, newXValue.AdjustCenterX());
                    JointLines[buttonIndex + 2].SetValue(Line.Y2Property, newYValue.AdjustCenterY());

                    JointLines[buttonIndex].SetValue(Line.X1Property, newXValue.AdjustCenterX());
                    JointLines[buttonIndex].SetValue(Line.Y1Property, newYValue.AdjustCenterY());
                }
                else
                {
                    JointLines[buttonIndex].SetValue(Line.X1Property, newXValue.AdjustCenterX());
                    JointLines[buttonIndex].SetValue(Line.Y1Property, newYValue.AdjustCenterY());
                }

            }
        }
        private void DrawLines(List<Line> lines)
        {
            LineHelpers.DrawLine(HeadJoint, ShoulderCenter, SketlonCanvas, lines[0]);
            LineHelpers.DrawLine(ElbowLeft, ShoulderCenter, SketlonCanvas, lines[1]);
            LineHelpers.DrawLine(ElbowRight, ShoulderCenter, SketlonCanvas, lines[2]);
            LineHelpers.DrawLine(HandLeft, ElbowLeft, SketlonCanvas, lines[3]);
            LineHelpers.DrawLine(HandRight, ElbowRight, SketlonCanvas, lines[4]);
            LineHelpers.DrawLine(ShoulderCenter, BackCenter, SketlonCanvas, lines[5]);
            LineHelpers.DrawLine(KneeLeft, BackCenter, SketlonCanvas, lines[6]);
            LineHelpers.DrawLine(KneeRight, BackCenter, SketlonCanvas, lines[7]);
            LineHelpers.DrawLine(FootLeft, KneeLeft, SketlonCanvas, lines[8]);
            LineHelpers.DrawLine(FootRight, KneeRight, SketlonCanvas, lines[9]);
        }

        private void CaptureClick(object sender, RoutedEventArgs e)
        {
            captureCount++;
            ExtractFrameAndSave();
            AddListItem();
        }

        private void AddListItem()
        {
            CheckBox chc = new CheckBox();
            chc.CommandParameter = captureCount.ToString();
            chc.Content = string.Concat(captureCount, " View");
            chc.Click += chc_Click;
            CaptureBox.Items.Add(chc);
        }

        protected void chc_Click(object sender, RoutedEventArgs e)
        {
            CheckBox chc = (sender) as CheckBox;
            int index = GetCheckBoxIndex(chc);
            DrawSketlon(SketlonList[index]);
        }

        private void DrawSketlon(SketlonFrame frame)
        {

            for (int i = 0; i < frame.Bones.Count; i++)
            {
                JointLines[i].SetValue(Line.X1Property, frame.Bones[i].X1.AdjustCenterX());
                JointLines[i].SetValue(Line.X2Property, frame.Bones[i].X2.AdjustCenterX());
                JointLines[i].SetValue(Line.Y1Property, frame.Bones[i].Y1.AdjustCenterY());
                JointLines[i].SetValue(Line.Y2Property, frame.Bones[i].Y2.AdjustCenterY());
                if (i == 5)
                {
                    buttonList[i].SetValue(Canvas.LeftProperty, frame.Bones[i].X2);
                    buttonList[i].SetValue(Canvas.TopProperty, frame.Bones[i].Y2);
                    ShoulderCenter.SetValue(Canvas.LeftProperty, frame.Bones[i].X1);
                    ShoulderCenter.SetValue(Canvas.TopProperty, frame.Bones[i].Y1);
                }
                else
                {
                    buttonList[i].SetValue(Canvas.LeftProperty, frame.Bones[i].X1);
                    buttonList[i].SetValue(Canvas.TopProperty, frame.Bones[i].Y1);
                }
            }
        }
        private int GetCheckBoxIndex(CheckBox chc)
        {
            int index = Convert.ToInt32(chc.CommandParameter)-1;
            return index;
        }
        private void ExtractFrameAndSave()
        {
            SketlonFrame frame = new SketlonFrame();
            frame.Bones = new List<Bone>();
            Bone headBone = new Bone(LineHelpers.GetDegree(JointLines[0]), JointLines[0]);
            Bone elbowLeftBone = new Bone(LineHelpers.GetDegree(JointLines[1]), JointLines[1]);
            Bone elbowRightBone = new Bone(LineHelpers.GetDegree(JointLines[2]), JointLines[2]);
            Bone handLeftBone = new Bone(LineHelpers.GetDegree(JointLines[3]), JointLines[3]);
            Bone handRightBone = new Bone(LineHelpers.GetDegree(JointLines[4]), JointLines[4]);
            Bone back = new Bone(LineHelpers.GetDegree(JointLines[5]), JointLines[5]);
            Bone kneeLeftBone = new Bone(LineHelpers.GetDegree(JointLines[6]), JointLines[6]);
            Bone kneeRightBone = new Bone(LineHelpers.GetDegree(JointLines[7]), JointLines[7]);
            Bone footLeft = new Bone(LineHelpers.GetDegree(JointLines[8]), JointLines[8]);
            Bone footRight = new Bone(LineHelpers.GetDegree(JointLines[9]), JointLines[9]);
            frame.Bones.Add(headBone);
            frame.Bones.Add(elbowLeftBone);
            frame.Bones.Add(elbowRightBone);
            frame.Bones.Add(handLeftBone);
            frame.Bones.Add(handRightBone);
            frame.Bones.Add(back);
            frame.Bones.Add(kneeLeftBone);
            frame.Bones.Add(kneeRightBone);
            frame.Bones.Add(footLeft);
            frame.Bones.Add(footRight);
            SketlonList.Add(frame);
        }

        private void SaveXML(object sender, RoutedEventArgs e)
        {
            XmlSerializer serializer = new XmlSerializer(typeof(List<SketlonFrame>));
            TextWriter writer = new StreamWriter("data.xml");
            serializer.Serialize(writer, SketlonList);
        }

        private void PlayStream(object sender, RoutedEventArgs e)
        {
            BackgroundWorker worker = new BackgroundWorker();
            worker.WorkerReportsProgress = true;
            List<SketlonFrame> ToBeRepeatedList = new List<SketlonFrame>();
            worker.DoWork += delegate(object s, DoWorkEventArgs args)
            {
                for (int i = 0; i < SketlonList.Count; i++)
                {
                    InvokeAndDraw(SketlonList[i]);
                    if (i < SketlonList.Count - 1 && SketlonList[i].RepeatCount > 0)
                    {
                        ToBeRepeatedList.Add(SketlonList[i]);
                        if (SketlonList[i].RepeatIndex != SketlonList[i + 1].RepeatIndex)
                        {
                            for (int j = 0; j < SketlonList[i].RepeatCount-1; j++)
                            {
                                for (int k = 0; k < ToBeRepeatedList.Count; k++)
                                {
                                    InvokeAndDraw(ToBeRepeatedList[k]);
                                }
                            }
                            ToBeRepeatedList.Clear();
                        }
                    }
                    else if (i == SketlonList.Count - 1 && SketlonList[i].RepeatCount > 0)
                    {
                        ToBeRepeatedList.Add(SketlonList[i]);
                        for (int j = 0; j < SketlonList[i].RepeatCount-1; j++)
                        {
                            for (int k = 0; k < ToBeRepeatedList.Count; k++)
                            {
                                InvokeAndDraw(ToBeRepeatedList[k]);
                            }
                        }
                        ToBeRepeatedList.Clear();
                    }

                }
            };
            worker.RunWorkerAsync();

        }
        private void InvokeAndDraw(SketlonFrame frame)
        {
            this.Dispatcher.Invoke((Action)(() =>
            {
                DrawSketlon(frame);
            }));
            Thread.Sleep(600);
        }
        private void Slider_ValueChanged_1(object sender, RoutedPropertyChangedEventArgs<double> e)
        {
            RepeatCount.Content = e.NewValue.ToString();
        }

        private void SetRepeatClick(object sender, RoutedEventArgs e)
        {
            UniqueRepeatIndex++;
            foreach (var item in CaptureBox.Items)
            {

                CheckBox chc = item as CheckBox;
                int index = GetCheckBoxIndex(chc);
                if (chc.IsChecked.ToBool())
                {
                    SketlonList[index].RepeatIndex = UniqueRepeatIndex;
                    SketlonList[index].RepeatCount = RepeatCount.Content.ToInt();
                    string content = chc.Content as string;
                    string whitespace = GetWhiteSpace(RepeatCount.Content);
                    chc.Content = whitespace + chc.CommandParameter.ToString() + "View"  + " Repeat : " + RepeatCount.Content;
                }
            }
        }

        private string GetWhiteSpace(object p)
        {
            string whiteSpace = "";
            int repeatCount = Convert.ToInt32(p);
            for (int i = 0; i < repeatCount; i++)
            {
                whiteSpace += " ";
            }
            return whiteSpace;
        }

        private void CleanStream(object sender, RoutedEventArgs e)
        {
            SketlonList.Clear();
            CaptureBox.Items.Clear();
        }

        private void CleanRepeat(object sender, RoutedEventArgs e)
        {
            foreach (var item in CaptureBox.Items)
            {
                CheckBox chc = item as CheckBox;
                int index = GetCheckBoxIndex(chc);
                if (chc.IsChecked.ToBool())
                {
                    SketlonList[index].RepeatCount = 0;
                }
            }
            UniqueRepeatIndex--;
        }
    }
}
